﻿using Microsoft.Practices.Prism.Interactivity.InteractionRequest;
using RedisDomain;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows.Input;
using StackExchange.Redis;
using Microsoft.Practices.Prism.Regions;
using System.Threading.Tasks;

namespace RedisModule.ViewModels
{
    public class RedisConnectionVm : BindableBase
    {
        private IRegionManager _regionManager;
        private bool _isSelected;
        private ConnectionMultiplexer _redis;
        private RedisDatabaseVm _currentRedisDatabase;


        public RedisConnectionVm()
        {
            OKCommand = new RelayCommand(TestConnect);
            ReloadCommand = new RelayCommand(Reload);
            CancelCommand = new RelayCommand(CancelConnect);
            CloseTabCommand = new RelayCommand(CloseTab);

            Parent = ModuleUtils.Resolve<ConnectManageVm>();

            RaiseCannotConnectRequest = new InteractionRequest<Notification>();
            _regionManager = ModuleUtils.Resolve<RegionManager>();

            IpAddress = "127.0.0.1";

            Port = 1428;

            Tabs = new ObservableCollection<TabItemInfo>();
            ClientListTabs = new ObservableCollection<TabItemInfo>();

            RedisDatabaseVms = new ObservableCollection<RedisDatabaseVm>();

            for (int i = 0; i < 16; i++)
            {
                var model = new RedisDatabaseVm(this,i);

                model.SelectedChanged += RedisDatabaseVm_SelectedChanged;
                RedisDatabaseVms.Add(model);
            }
        }

      

        private void RedisDatabaseVm_SelectedChanged(object sender, EventArgs e)
        {
            this.Parent.CurrentRedisConnection = this;

            CurrentRedisDatabase = sender as RedisDatabaseVm;

            //var region = _regionManager.Regions["CenterRegion"];

            //var view = region.GetView("CenterDbView"+ CurrentRedisDatabase);
            //if (view == null)
            //{
            //    view = ModuleUtils.Resolve<Views.CenterDbView>();
            //    region.Add(view, "CenterDbView"+ CurrentRedisDatabase);
            //}
           
            //region.Activate(view);
        }

        public event EventHandler SelectedChanged;
           
        public string IpAddress { get; set; }
        public ConnectManageVm Parent { get; set; }

        

        public int Port { get; set; }

        public RedisDatabaseVm CurrentRedisDatabase
        {
            get { return _currentRedisDatabase; }
            set { SetProperty(ref _currentRedisDatabase, value, () => CurrentRedisDatabase); }
        }

        private void OnSelectedChanged()
        {
            if(SelectedChanged != null)
            {
                SelectedChanged(this, new EventArgs());
            }

            Reload(null);
        }


        public ObservableCollection<TabItemInfo> Tabs { get; set; }
        public ObservableCollection<TabItemInfo> ClientListTabs { get; set; }

        public ObservableCollection<RedisDatabaseVm> RedisDatabaseVms { get; private set; }

        public bool DialogResult { get; private set; }

        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if(SetProperty(ref _isSelected, value, () => IsSelected) && IsSelected)
                {
                    OnSelectedChanged();
                }
            }
        }

        public bool IsConnected
        {
            get
            {
                return _redis != null && _redis.IsConnected;
            }
        }

        public ICommand OKCommand { get; private set; }
        public ICommand ReloadCommand { get; private set; }

        public ICommand CancelCommand { get; private set; }
        public ICommand CloseTabCommand { get; private set; }

        public InteractionRequest<Notification> RaiseCannotConnectRequest { get; private set; }

        internal IEnumerable<RedisKey> Keys(int dbIndex)
        {
            return GetServer().Keys(dbIndex);
        }

        private IServer _server;
        private IServer GetServer()
        {
            if(_server == null)
            {
                var endPoint = _redis.GetEndPoints().FirstOrDefault();
                _server = _redis.GetServer(endPoint);
            }
            return _server;
        }


        public Task<RedisValue> GetValue(int db,RedisKey key)
        {
            Logger.Log(string.Format("GET {0}", key));
            var task = _redis.GetDatabase(db).StringGetAsync(key);

            task.ContinueWith(o => NotificationUtils.Show("Get {0} done! the result is {1}.", key, o.Result));

            return task;
        }

        internal Task<bool> SetValue(int db, RedisKey key, RedisValue value)
        {
            Logger.Log(string.Format("SET {0} {1}", key,value));
            var task = _redis.GetDatabase(db).StringSetAsync(key, value);


            task.ContinueWith(o => { if (o.Result) NotificationUtils.Show("Set {0} {1} done!", key, value); });
            return task;
        }

        internal Task<bool> DeleteKey(int db, string key)
        {
            Logger.Log(string.Format("DEL {0}", key));
            var task = _redis.GetDatabase(db).KeyDeleteAsync(key);

            task.ContinueWith(o => { if (o.Result) NotificationUtils.Show("Del {0} done!", key); });

            return task;
        }

        internal Task<bool> Rename(int db, string key,string newKey)
        {
            Logger.Log(string.Format("RENAME {0} {1}", key, newKey));
            var task = _redis.GetDatabase(db).KeyRenameAsync(key, newKey);

            task.ContinueWith(o => { if (o.Result) NotificationUtils.Show("Rename {0} {1} done!" ,key,newKey); });

            return task;
        }

        private void TestConnect(object obj)
        {
            try
            {
                _redis = ConnectionMultiplexer.Connect(new ConfigurationOptions() { AllowAdmin = true,EndPoints = { {IpAddress,Port } } });
                DialogResult = true;

                RaiseCannotConnectRequest.Raise(new Notification
                {
                    Title = "提示",
                    Content = "连接成功",
                });
                Close();
            }
            catch (Exception)
            {
                RaiseCannotConnectRequest.Raise(new Notification
                {
                    Title = "提示",
                    Content = "连接失败",
                });
            }
        }

        private void CancelConnect(object obj)
        {
            DialogResult = false;
            Close();
        }

        private void CloseTab(object obj)
        {
            var tabItem = (System.Windows.Controls.TabItem)obj;
            var view = tabItem.Content;
            var region = _regionManager.Regions["CenterRegion"];

            if (region != null)
            {
                region.Remove(view);
            }
        }


        private void Reload(object obj)
        {
            if (_redis.IsConnected)
            {
                var info = GetServer().Info();

                Tabs.Clear();
                foreach (var item in info)
                {
                    Tabs.Add(new TabItemInfo(item));
                }
            }
            GetClientList();
        }

        private void GetClientList()
        {
            var clientInfos = GetServer().ClientListAsync().Result;

            ClientListTabs.Clear();

            foreach (var item in clientInfos)
            {
                ClientListTabs.Add(new TabItemInfo(item));
            }

          
                //.ContinueWith(o => o.Result, TaskScheduler.FromCurrentSynchronizationContext());
        }




        public override string ToString()
        {
            return string.Format("{0}:{1}", IpAddress, Port);
        }
    }
}
